#include "log.h"

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

/*
 *@日志的初始化操作
 */
int serverLogInit(struct webServerCtx *serverctx){
#define LOG_FILE_NAME_MAX 100
	int iRet = RET_ERROR;
	struct tm *logtime;
	time_t gettime;
	char logFile[LOG_FILE_NAME_MAX];
	if(!serverctx){
		fprintf(stderr,"[errno]error:%s in file:[%s] func:[%s] line:[%d]!\n", strerror(errno), __FILE__,__func__,__LINE__);
		return RET_ERROR;
	}
	serverctx->log = (struct logOutPut *)malloc(sizeof(struct logOutPut));
	if(!serverctx->log){
		return RET_ERROR;
	}
	memset(serverctx->log, 0, sizeof(struct logOutPut));
	serverctx->log->logPath = strdup(serverctx->opt->outPutLogPath);
	serverctx->log->OutPutMode = serverctx->opt->OutPutMode;
	serverctx->log->iovcnt = serverctx->opt->buffBlockNum;
	serverctx->log->buffLen = serverctx->opt->buffLogLen;
	if(serverctx->log->iovcnt != 0){
		iRet = formatLogBuff(&(serverctx->log));
		if (iRet == RET_ERROR){
			goto failed;
		}
	}
	memset(logFile, '\0', LOG_FILE_NAME_MAX);
	gettime = time(NULL);
	logtime = localtime(&gettime);
	sprintf(logFile, "%s/%d-%d-%d.log", serverctx->log->logPath, logtime->tm_year + 1900, logtime->tm_mon + 1, logtime->tm_mday);
#ifdef  __DEBUG_ON__
	DEBUG_TRACE(("[debug]logFile:%s\n", logFile));	
#endif 
	iRet = isExistFile(logFile);
	if ( iRet == RET_OK ){
		//日志文件已经存在;
		serverctx->log->logfd = openFile(logFile, O_RDWR|O_APPEND);
		if(serverctx->log->logfd < 0){
			fprintf(stderr,"[error]:%s in file:[%s] func:[%s] line:[%d]!\n", strerror(errno), __FILE__,__func__,__LINE__);
			goto failed;
		}
#ifdef __DEBUG_ON__
		DEBUG_TRACE(("[debug]logFile:%s  has been open!!!!\n", logFile));	
#endif 
	}else{
		//文件不存在 我们创建并且打开它;
		serverctx->log->logfd = openFile(logFile, O_RDWR|O_APPEND|O_CREAT);
		if (serverctx->log->logfd < 0){
			fprintf(stderr,"[error]:%s in file:[%s] func:[%s] line:[%d]!\n", strerror(errno), __FILE__,__func__,__LINE__);
			goto failed;
		}
	} 
	return RET_OK;
failed:
	serverLogDeinit(serverctx->log);
	return RET_ERROR;
}

/*
 *@brief:
 */
void serverLogDeinit(struct logOutPut *logctx){
	if(!logctx){
		fprintf(stderr, "[error]:%s in file:[%s]  func:[%s]  line:[%d]!\n", strerror(errno), __FILE__,__func__,__LINE__);
		return;
	}
	if(logctx->mapAddr){
		free(logctx->mapAddr);
		logctx->mapAddr = NULL;
	}
	if(logctx->ivec){
		free(logctx->ivec);
		logctx->ivec = NULL;
	}
	if(logctx->logfd!=0){
		close(logctx->logfd);
	}
	if(logctx->logPath){
		free(logctx->logPath);
		logctx->logPath = NULL;
	}
	if(logctx){
		free(logctx);
		logctx = NULL;
	}
}

/*@brief:
 *
 */
int formatLogBuff(struct logOutPut **logctx){
	struct logOutPut *tmpctx = *logctx;
	int index = 0;
	tmpctx->mapAddr = (char *)malloc(tmpctx->buffLen  * tmpctx->iovcnt);
	if (!tmpctx->mapAddr){
		fprintf(stderr, "[error]%s in file:[%s] func:[%s] line:[%d]!\n", strerror(errno), __FILE__,__func__,__LINE__);
		return RET_ERROR;
	}
	tmpctx->ivec = (struct iovec *)malloc(sizeof(struct iovec)*tmpctx->iovcnt);
	if (!tmpctx->ivec){
		fprintf(stderr, "[error]%s in file:[%s] func:[%s] line:[%d]!\n", strerror(errno), __FILE__,__func__,__LINE__);
		return RET_ERROR;
	}
	for ( index = 0; index < tmpctx->iovcnt; index++){
		tmpctx->ivec[index].iov_base = (char *)tmpctx->mapAddr + tmpctx->buffLen * index;
		tmpctx->ivec[index].iov_len = 0;
	}
	tmpctx->currindex = 0;
	*logctx = tmpctx;
	return RET_OK;
}

/*
 *@brief:
 */
void LogInfo(struct webServerCtx *serverctx, const char *fmt,...){
	if(!serverctx){
		fprintf(stderr, "[error]get unavaliable args in [file]:%s [func]:%s [LINE]:%d\n", __FILE__,__func__,__LINE__);
		return;
	}
    pthread_mutex_lock(&mutex);
	struct logOutPut *log = serverctx->log;
	va_list ap;
	time_t logtime;
	size_t len = 0;
	struct tm * accesstime = NULL;
	logtime = time(NULL);
	accesstime = localtime(&logtime);
	if(log->currindex == log->iovcnt - 1){
		writev(log->logfd, log->ivec, log->iovcnt);
		fdatasync(log->logfd);
		log->currindex = 0;
		memset(log->mapAddr, '\0', log->buffLen * log->iovcnt);
	}
	char *buf = (char *)(log->ivec[log->currindex].iov_base);

  	if(buf&&accesstime){
        len = sprintf(buf+len, "[info] %d-%d-%d-%d:%d:%d ", accesstime->tm_year + 1900, accesstime->tm_mon + 1, accesstime->tm_mday, accesstime->tm_hour, accesstime->tm_min, accesstime->tm_sec);
	    //追加日志信息
		va_start(ap, fmt);
		len += vsprintf(buf + len, fmt, ap);
		va_end(ap);
		log->ivec[log->currindex].iov_len = len;

    }
    log->currindex++;
    pthread_mutex_unlock(&mutex); 
    return;
}


